module IPFS.Client.Command.Key(
 list,
 gen,
 rm,
 rename,
 ReNameInfo(..),
 KeyListInfo(..),
 KeyInfo(..)
) where

import Prelude

import Data.Argonaut (class DecodeJson, Json, decodeJson, fromString)
import Data.Argonaut.Decode ((.:))
import Data.Either (Either)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..))
import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff)
import Foreign.Object as O
import IPFS.Client (Client)
import IPFS.Client.Command (Command, defCommand, genQSObject)
import IPFS.Client.Utils.SendRequest (execJsonCommand)

------------------------------list-----------------------------
newtype KeyInfo = KeyInfo {
 name::String,
 id::String
}

derive instance genericKeyInfo :: Generic KeyInfo _
instance showKeyInfo :: Show KeyInfo where
  show s = genericShow s

instance keyInfoDecodeJson :: DecodeJson KeyInfo where
  decodeJson::Json -> Either String KeyInfo
  decodeJson json = do
    dJson   <- decodeJson json
    name    <- dJson .: "Name"
    id      <- dJson .: "Id"
    pure $ KeyInfo {name:name,id:id}

newtype KeyListInfo = KeyListInfo (Array KeyInfo)

derive instance genericKeyListInfo :: Generic KeyListInfo _
instance showKeyListInfo :: Show KeyListInfo where
  show s = genericShow s

instance keyListInfoDecodeJson :: DecodeJson KeyListInfo where
  decodeJson::Json -> Either String KeyListInfo
  decodeJson json = do
    dJson   <- decodeJson json
    arr    <- dJson .: "Keys"
    pure $ KeyListInfo arr

lsCommand::Command
lsCommand = defCommand {path = "key/list",args = Nothing,qs = O.empty}

list::Client -> Aff (Either String KeyListInfo)
list client = execJsonCommand client lsCommand

------------------------------list-----------------------------

genCommand::String ->  String -> Maybe Int -> Command
genCommand name keyType size = defCommand {path = "key/gen",
                                           args = Just [fromString name],
                                           qs = genQSObject ["type" /\ Just keyType , "size" /\ (show <$> size)] O.empty}

gen::Client -> String ->  String -> Maybe Int -> Aff (Either String KeyInfo)
gen client name keyType size = execJsonCommand client $ genCommand name keyType size

------------------------------rm-----------------------------

rmCommand::String -> Command
rmCommand name = defCommand  {path = "key/rm",args = Just [fromString name],qs = O.empty}

rm::Client -> String -> Aff (Either String KeyListInfo)
rm client name =  execJsonCommand client $ rmCommand name

------------------------------rename-----------------------------

newtype ReNameInfo = ReNameInfo {
  was::String,
  now::String,
  id::String,
  overwrite::Boolean
}

derive instance genericReNameInfo :: Generic ReNameInfo _
instance showReNameInfo :: Show ReNameInfo where
  show s = genericShow s

instance reNameInfoDecodeJson :: DecodeJson ReNameInfo where
  decodeJson::Json -> Either String ReNameInfo
  decodeJson json = do
    dJson     <- decodeJson json
    was       <- dJson .: "Was"
    now       <- dJson .: "Now"
    id        <- dJson .: "Id"
    overwrite <- dJson .: "Overwrite"
    pure $ ReNameInfo {was:was,now:now,id:id,overwrite:overwrite }

renameCommand::String -> String -> Maybe Boolean -> Command
renameCommand  oldName newName force = defCommand {path = "key/rename",
                                                         args = Just [fromString oldName,fromString newName],
                                                         qs = genQSObject ["force" /\ (show <$> force)] O.empty}

rename::Client -> String -> String -> Maybe Boolean  -> Aff (Either String ReNameInfo)
rename client oldName newName force = execJsonCommand client $ renameCommand oldName newName force